package com.umakr.ax.security.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.umakr.ax.security.core.jwt.JwtConfigProperties;
import com.umakr.ax.security.core.jwt.JwtTokenUtils;
import com.umakr.ax.security.enums.ResType;
import com.umakr.ax.security.mapper.RoleMapper;
import com.umakr.ax.security.model.Role;
import com.umakr.ax.security.model.User;
import com.umakr.ax.security.mapper.UserMapper;
import com.umakr.ax.core.base.BaseService;
import com.umakr.ax.security.model.vo.UserMenuVO;
import com.umakr.ax.security.model.vo.UserVO;
import com.baomidou.mybatisplus.plugins.Page;
import com.umakr.ax.utils.WebUtil;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author gx
 * @since 2017-04-25
 */
@Service
public class UserService extends BaseService<UserMapper, User>{

    @Autowired
    SecurityUserDetailsServiceImpl securityUserDetailsServiceImpl;
    @Autowired
    JwtTokenUtils jwtTokenUtils;
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    RoleMapper roleMapper;

    @Autowired
    private JwtConfigProperties jwtConfigProperties;

    @Autowired
    private UserMapper userMapper;
    /**
     * 登录并生成access_token
     * @auth gx
     * @since 2017-04-25
     * @param username 用户名
     * @param password 密码
     * @return access_token
     */
    public String login(String username, String password) {
        UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
        final Authentication authentication = authenticationManager.authenticate(upToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        final UserDetails userDetails = securityUserDetailsServiceImpl.loadUserByUsername(username);
        return jwtTokenUtils.generateToken(userDetails);
    }
    public String weXinLoginToken(Long userId){
        final UserDetails userDetails = securityUserDetailsServiceImpl.loadUserByUsername(userId + "@");
        return jwtTokenUtils.generateToken(userDetails);
    }

    /**
     * access_token刷新
     * @param oldToken 旧access_token
     * @return 新的token
     */
    public String refresh(String oldToken) {
        final String token = oldToken.substring(jwtConfigProperties.getHeadToken().length());
        String username = jwtTokenUtils.getUsernameFromToken(token);
        User user = (User) securityUserDetailsServiceImpl.loadUserByUsername(username);
        if (jwtTokenUtils.canTokenBeRefreshed(token, user.getLastPdRestTime())){
            return jwtTokenUtils.refreshToken(token);
        }
        return null;
    }

    /**
     * 检测用户名是否存在
     * @param username 用户名
     */
    public Boolean exitUsername(String username){
        UserDetails userDetails = securityUserDetailsServiceImpl.loadUserByUsername(username);
        return userDetails != null;
    }

    /**
     * 检测用户名是否存在
     * @param username 用户名
     */
    public Boolean checkUsernameExit(String username){
        User user = new User();
        user.setAccount(username);
        user = userMapper.selectOne(user);
        return user != null;
    }
    /**
     * 分页查询用户信息
     * @param userVO 查询条件
     */
    public Page<UserVO> queryUserPage(UserVO userVO){
        return baseMapper.queryUserPage(userVO);
    }

    /**
     * hmi密码修改
     * @param oldPwd 旧密码
     * @param newPwd 新密码
     * @param confirmPwd 确认新密码
     * @return
     */
    public Object modifyPwd(String account,String oldPwd, String newPwd, String confirmPwd) {
        if(!StringUtils.isNotEmpty(oldPwd)){
            return resultMap(0,"旧密码不能为空");
        }
        if(!StringUtils.isNotEmpty(newPwd)){
            return resultMap(-1,"新密码不能为空");
        }
        if(!StringUtils.isNotEmpty(confirmPwd)){
            return resultMap(-2,"确认密码不能为空");
        }
        if(!newPwd.equals(confirmPwd)){
            return resultMap(-3,"新密码与确认密码不正确。");
        }
        return changePwd(account,newPwd,confirmPwd);
    }

    public Object changePwd(String account, String newPwd, String confirmPwd){
        EntityWrapper<User> userEntityWrapper = new EntityWrapper<>();
        userEntityWrapper.eq("account",account);
        User user = selectOne(userEntityWrapper);
        try{
            if(newPwd.equals(confirmPwd)){
                user.setPassword(WebUtil.getBean(BCryptPasswordEncoder.class).encode(newPwd));
                update(user);
                return  resultMap(1,"操作成功。");
            }else{
                return resultMap(-3,"新密码与确认密码不正确。");
            }
        }catch (BadCredentialsException exception){
            return resultMap(-4,"密码不正确。");
        }
    }

    public Object registerUser(String account,String pwd) {
        if(!StringUtils.isNotEmpty(account)){
            return resultMap(0,"手机号不能为空");
        }
        if(!StringUtils.isNotEmpty(pwd)){
            return resultMap(0,"密码不能为空");
        }

        User user = new User();
        user.setAccount(account);
        user.setStatus(1);
        user.setPassword(WebUtil.getBean(BCryptPasswordEncoder.class).encode(pwd));
        user.setLastLoginTime(new Date());
        update(user);

        return user;
    }

    public List<UserMenuVO> queryUserMenu(Long userId){
        List<Role> listRole = roleMapper.queryRoleByUserId(userId);
        boolean isAdmin = false;
        for(Role role : listRole){
            if("ROLE_ADMIN".equals(role.getRoleCode())){
                isAdmin = true;
            }
        }
        List<UserMenuVO> userMenuVOs = null;
        if(isAdmin){
            userMenuVOs = baseMapper.queryUserMenuByAdmin();
        }else{
            userMenuVOs = baseMapper.queryUserMenu(userId);
        }

        List<UserMenuVO> userMenuReturnedVOs = Lists.newArrayList();
        for(UserMenuVO userMenuVO : userMenuVOs){
            if(ResType.MODULE.eq(userMenuVO.getResType())){
                userMenuReturnedVOs.add(userMenuVO);
                singleMenu(userMenuVO,userMenuVOs);
            }
        }

        List<UserMenuVO> listUserMenuReturnedVOs = Lists.newArrayList();
        for(UserMenuVO userMenuVO : userMenuVOs){
            if(userMenuVO.getResParentId() == null){
                listUserMenuReturnedVOs.add(userMenuVO);
            }
        }

        return  listUserMenuReturnedVOs;
    }

    public void singleMenu(UserMenuVO userMenuVO,List<UserMenuVO> userMenuVOList){
        for(UserMenuVO userMenuVO1 : userMenuVOList){
            if(userMenuVO1.getResParentId()!=null && userMenuVO1.getResParentId().equals( userMenuVO.getId() )){
                userMenuVO.getChildren().add(userMenuVO1);
                if(ResType.ACTION.eq(userMenuVO1.getResType())){
                    singleMenu(userMenuVO1,userMenuVOList);
                }
            }
        }
    }

    public Map<String,Object> getUserDetailsByUserId(Long userId){
        return baseMapper.getUserDetailsByUserId(userId);
    }

}
